﻿using PARK.Common.Core.Manager;
using PARK.Common.Enum;
using PARK.Common.Extension;
using PARK.Common.Filter;
using PARK.Dependency;
using PARK.DynamicApiController;
using PARK.FriendlyException;
using PARK.Accessctl.Interfaces.AccessCtlauthTask;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PARK.Accessctl.Entitys;
using PARK.Accessctl.Entitys.Dto.AccessCtlauthTask;
using Yitter.IdGenerator;
using PARK.Common.Helper;
using PARK.JsonSerialization;
using PARK.System.Entitys.Permission;
using PARK.System.Interfaces.Permission;
using PARK.Common.Util;
using PARK.CardAcct.Entitys;
using System.Text;
using PARK.Accessctl.Entitys.Dto.AccessCtl;
using PARK.BussinCache.Interfaces;

namespace PARK.Accessctl.AccessCtlauthTask
{
    /// <summary>
    /// 权限管理服务
    /// </summary>
    [ApiDescriptionSettings(Tag = "Access", Name = "CtlauthTask", Order = 200)]
    [Route("api/access/[controller]")]
    public class AccessCtlauthTaskService : IAccessCtlauthTaskService, IDynamicApiController, ITransient
    {
        private readonly ISqlSugarRepository<AccessCtlauthTaskEntity> _accessCtlauthTaskRepository;
        private readonly SqlSugarScope _db;
        private readonly IUserManager _userManager;
        private readonly IOrganizeService _organizeService; // 机构表仓储
        private readonly IParkCacheRepository _parkCacheRepository;

        /// <summary>
        /// 初始化一个<see cref="AccessCtlauthTaskService"/>类型的新实例
        /// </summary>
        public AccessCtlauthTaskService(
            ISqlSugarRepository<AccessCtlauthTaskEntity> accessCtlauthTaskRepository,
            IUserManager userManager,
            IOrganizeService organizeService,
            IParkCacheRepository parkCacheRepository)
        {
            _accessCtlauthTaskRepository = accessCtlauthTaskRepository;
            _db = _accessCtlauthTaskRepository.Context;
            _userManager = userManager;
            _organizeService = organizeService;
            _parkCacheRepository = parkCacheRepository;
        }

        /// <summary>
        /// 获取权限管理
        /// </summary>
        /// <param name="id">参数</param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public async Task<dynamic> GetInfo(string id)
        {
            var entity = await _db.Queryable<AccessCtlauthTaskEntity>().FirstAsync(p => p.TaskId == id);
            var output = entity.Adapt<AccessCtlauthTaskInfoOutput>();
            return output;
        }

        /// <summary>
		/// 获取权限管理列表
		/// </summary>
		/// <param name="input">请求参数</param>
		/// <returns></returns>
        [HttpGet("")]
        public async Task<dynamic> GetList([FromQuery] AccessCtlauthTaskListQueryInput input)
        {
            var userInfo = await _userManager.GetUserInfo();
            if (userInfo != null && userInfo.UserAdminFlag != 2 && !string.IsNullOrEmpty(userInfo.companyId))
            {
                var sidx = input.sidx == null ? "creatorTime" : input.sidx;
                var organizeIds = new List<string>();
                if (!input.organizeId.IsNullOrEmpty())
                    organizeIds = await GetSubOrganizeIds(input.organizeId);
                //最后下发日期
                List<string> queryBillDate = input.lastIssueTime != null ? input.lastIssueTime.Split(',').ToObeject<List<string>>() : null;
                DateTime? startBilldate = queryBillDate != null ? Ext.GetDateTime(queryBillDate.First()) : null;
                DateTime? endBilldate = queryBillDate != null ? Ext.GetDateTime(queryBillDate.Last()) : null;
                var data = await _db.Queryable<AccessCtlauthTaskEntity>()
                    //公司权限
                    .Where(p => p.CompanyId.Equals(userInfo.companyId))
                    .Where(t => t.DeleteMark == 0)
                    //关键字查询
                    .WhereIF(!input.keyword.IsNullOrEmpty(), p => p.CtlSn.Contains(input.keyword) || p.CardNo.Contains(input.keyword) || p.JobNo.Contains(input.keyword) || p.ReallName.Contains(input.keyword))
                    //组织机构
                    .WhereIF(organizeIds.Any(), u => organizeIds.Contains(SqlFunc.ToString(u.DepartId)))
                    .WhereIF(!input.doorNo.IsNullOrEmpty(), p => p.Door1No.Equals(input.doorNo) || p.Door2No.Equals(input.doorNo) || p.Door3No.Equals(input.doorNo) || p.Door4No.Equals(input.doorNo))
                    .WhereIF(!string.IsNullOrEmpty(input.ctlSn), p => p.CtlSn.Contains(input.ctlSn))
                    //下发日期查询
                    .WhereIF(queryBillDate != null, a => a.LastIssueTime >= new DateTime(startBilldate.ToDate().Year, startBilldate.ToDate().Month, startBilldate.ToDate().Day, 0, 0, 0))
                    .WhereIF(queryBillDate != null, a => a.LastIssueTime <= new DateTime(endBilldate.ToDate().Year, endBilldate.ToDate().Month, endBilldate.ToDate().Day, 23, 59, 59))
                     //任务状态
                     .WhereIF(!string.IsNullOrEmpty(input.taskStatus), p => p.TaskStatus.Equals(input.taskStatus))
                    .Select(it => new AccessCtlauthTaskListOutputs
                    {
                        taskId = it.TaskId,
                        ctlSn = it.CtlSn,
                        ctlName= it.ctlName,
                        door1No = it.Door1No,
                        door2No = it.Door2No,
                        door3No = it.Door3No,
                        door4No = it.Door4No,
                        jobNo = it.JobNo,
                        reallName = it.ReallName,
                        departName = it.DepartName,
                        cardNo = it.CardNo,
                        startTime = Convert.ToDateTime(it.StartTime).ToString("yyyy-MM-dd"),
                        endTime = Convert.ToDateTime(it.EndTime).ToString("yyyy-MM-dd"),
                        addorDel = it.AddorDel,
                        lastIssueTime = it.LastIssueTime,
                        issues = it.Issues,
                        doorAreaName = it.DoorAreaName,
                        ctlposition = it.Ctlposition,
                        taskStatus = it.TaskStatus,
                        creatorTime = it.CreatorTime
                    }).MergeTable().OrderBy(sidx + " " + input.sort).ToPagedListAsync(input.currentPage, input.pageSize);
                return PageResult<AccessCtlauthTaskListOutputs>.SqlSugarPageResult(data);
            }
            else
                return null;
        }

        /// <summary>
        /// 下属机构
        /// </summary>
        /// <param name="organizeId">机构ID</param>
        /// <returns></returns>
        [NonAction]
        public async Task<List<string>> GetSubOrganizeIds(string organizeId)
        {
            var data = await _organizeService.GetListAsync();
            data = data.TreeChildNode(organizeId, t => t.Id, t => t.ParentId);
            return data.Select(m => m.Id).ToList();
        }

        #region 批量下发门禁权限任务
        /// <summary>
        /// 批量下发门禁权限任务
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("CtlauthTaskCrBatchAdd")]
        public async Task CtlauthTaskCrBatchAdd([FromBody] AccessCtlauthTaskCrBatchInput input)
        {
            var userInfo = await _userManager.GetUserInfo();
            if (userInfo != null && userInfo.UserAdminFlag != 2 && !string.IsNullOrEmpty(userInfo.companyId))
            {
                try
                {
                    if (input.addctlList == null || input.addctlList.Count == 0)
                    {
                        throw PARKException.Bah("请选择控制器");
                    }
                    if (input.eyeList == null || input.eyeList.Count == 0)
                    {
                        throw PARKException.Bah("请选择人员");
                    }
                    List<AccessCtlauthTaskEntity> ctlauthTaskList = new List<AccessCtlauthTaskEntity>();
                    foreach (var item in input.addctlList)
                    {
                        var TaskCrInput = new AccessCtlauthTaskCrInput();
                        TaskCrInput.addorDel = input.ctlpass;
                        TaskCrInput.ctlId = item.ctlId;
                        TaskCrInput.ctlSn = item.ctlSN;
                        TaskCrInput.ctlName = item.ctlName;
                        TaskCrInput.doorAreaId = item.doorAreaId;
                        TaskCrInput.doorAreaName = item.doorAreaName;
                        TaskCrInput.ctlposition = item.ctlposition;
                        TaskCrInput.door1No = 1;
                        TaskCrInput.door2No = 0;
                        TaskCrInput.door3No = 0;
                        TaskCrInput.door4No = 0;
                        TaskCrInput.startTime = DateTime.Now;
                        TaskCrInput.CompanyId = userInfo.companyId;
                        TaskCrInput.CompanyName = userInfo.companyName;
                        TaskCrInput.endTime = !string.IsNullOrEmpty(input.Expirydate) ? Convert.ToDateTime(input.Expirydate) : DateTime.Now.AddYears(50);
                        TaskCrInput.issues = 0;
                        foreach (var eye in input.eyeList)
                        {
                            TaskCrInput.employeeId = eye.employeeId;
                            TaskCrInput.jobNo = eye.jobNo;
                            TaskCrInput.reallName = eye.reallName;
                            TaskCrInput.departId = eye.departId;
                            TaskCrInput.departName = eye.departName;
                            TaskCrInput.cardNo = eye.cardNo;
                            var Entity = TaskCrInput.Adapt<AccessCtlauthTaskEntity>();
                            Entity.Create();
                            Entity.CompanyId = userInfo.companyId;
                            Entity.CompanyName = userInfo.companyName;
                            Entity.IsDeleteTask = Entity.AddorDel == 2 ? 1 : 0;
                            ctlauthTaskList.Add(Entity);
                        } 
                    }
                    if (ctlauthTaskList != null && ctlauthTaskList.Count > 0)
                    {
                        var isOk = await _db.Insertable(ctlauthTaskList).ExecuteCommandAsync();
                        if (!(isOk > 0))
                        {
                            throw PARKException.Oh(ErrorCode.COM1000);
                        }
                        else
                        {
                            //写入任务队列
                            await _parkCacheRepository.SetAccAuthqueue(ctlauthTaskList);
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw PARKException.Oh(ex.Message);
                }
            }
            else
                throw PARKException.Bah("您的权限无法操作!");
        }
        #endregion

        #region 下发单个人门禁权限任务
        /// <summary>
        /// 下发单个人门禁权限任务
        /// </summary>
        /// <param name="input">参数</param>
        /// <returns></returns>
        [HttpPost("ctlauthTaskCtlAdd")]
        public async Task ctlauthTaskCtlAdd([FromBody] AccessCtlauthTaskCrSingeInput input)
        {
            var userInfo = await _userManager.GetUserInfo();
            if (userInfo != null && userInfo.UserAdminFlag != 2 && !string.IsNullOrEmpty(userInfo.companyId))
            {
                try
                {
                    if (string.IsNullOrEmpty(input.EmployeeId))
                    {
                        throw PARKException.Bah("请选择人员");
                    }
                    var EyeEntity = await _db.Queryable<EmployeeEntity>().FirstAsync(p => p.EmployeeId == input.EmployeeId);
                    List<AccessCtlauthTaskEntity> ctlauthTaskList = new List<AccessCtlauthTaskEntity>();
                    if (input.addctlList != null)
                    {
                        string _addCtlIds = "";
                        if (input.addctlList.Count > 0)
                        {
                            #region 处理需要添加权限
                            foreach (var item in input.addctlList)
                            {
                                if (!string.IsNullOrEmpty(item))
                                {
                                    _addCtlIds += "'" + item + "',";

                                    var _Ctlentity = await _db.Queryable<AccessCtlEntity>().FirstAsync(p => p.CtlId == item);
                                    if (_Ctlentity != null)
                                    {
                                        var TaskCrInput = new AccessCtlauthTaskCrInput();
                                        TaskCrInput.addorDel = 1;
                                        TaskCrInput.ctlId = _Ctlentity.CtlId;
                                        TaskCrInput.ctlSn = _Ctlentity.CtlSn;
                                        TaskCrInput.ctlName = _Ctlentity.CtlName;
                                        TaskCrInput.doorAreaId = _Ctlentity.DoorAreaId;
                                        TaskCrInput.doorAreaName = _Ctlentity.DoorAreaName;
                                        TaskCrInput.ctlposition = _Ctlentity.Ctlposition;
                                        TaskCrInput.door1No = 1;
                                        TaskCrInput.door2No = 0;
                                        TaskCrInput.door3No = 0;
                                        TaskCrInput.door4No = 0;
                                        TaskCrInput.startTime = DateTime.Now;
                                        TaskCrInput.endTime = !string.IsNullOrEmpty(input.Expirydate) ? Convert.ToDateTime(input.Expirydate) : DateTime.Now.AddYears(50);
                                        TaskCrInput.issues = 0;
                                        TaskCrInput.employeeId = input.EmployeeId;
                                        TaskCrInput.jobNo = EyeEntity.JobNum;
                                        TaskCrInput.reallName = EyeEntity.RealName;
                                        TaskCrInput.departId = EyeEntity.DepartId;
                                        TaskCrInput.departName = EyeEntity.DepartName;
                                        TaskCrInput.cardNo = EyeEntity.CardNo;
                                        TaskCrInput.CompanyId = userInfo.companyId;
                                        TaskCrInput.CompanyName = userInfo.companyName;
                                        var Entity = TaskCrInput.Adapt<AccessCtlauthTaskEntity>();
                                        Entity.Create();
                                        Entity.IsDeleteTask = 0;
                                        ctlauthTaskList.Add(Entity);
                                    }
                                }
                            }
                            if (_addCtlIds.Length > 0)
                            {
                                _addCtlIds = _addCtlIds.Substring(0, _addCtlIds.Length - 1);
                                StringBuilder _dbSql = new StringBuilder("select a.doorId,a.ctlId,b.ctlSN,b.ctlName,b.doorAreaId,b.doorAreaName,b.ctlposition,a.doorNo,a.doorName,b.isOnline,b.lastOnLineTime ");
                                _dbSql.Append(" from access_door a inner join access_ctl b on a.ctlId=b.ctlId where b.EnabledMark=1 and b.IsDeleted=0 and a.CompanyId='" + userInfo.companyId + "'");
                                _dbSql.AppendFormat(" and a.ctlId in ({0})", _addCtlIds);
                                _dbSql.Append(" order by a.ctlId,a.doorNo asc");
                                var _CtlauthDoors = await _db.SqlQueryable<AccessDoorListOutput>(_dbSql.ToString()).ToListAsync();
                                if (_CtlauthDoors != null)
                                {
                                    var _Ctls = _CtlauthDoors.DistinctBy(p => new { p.ctlId, p.ctlSN }).ToList();
                                    foreach (var item in _Ctls)
                                    {
                                        if (item != null)
                                        {
                                           
                                        }
                                    }
                                }
                            }
                            #endregion
                        }

                        #region 处理需删除权限
                        if (string.IsNullOrEmpty(_addCtlIds))
                            _addCtlIds = "''";
                        StringBuilder dbSql = new StringBuilder(" select a.* from access_ctl a where a.EnabledMark = 1 and a.IsDeleted = 0");
                        dbSql.AppendFormat(" and a.CompanyId= '{0}'", userInfo.companyId);
                        dbSql.AppendFormat(" and a.ctlId not in ({0})", _addCtlIds);
                        dbSql.Append(" and a.ctlId in (select ctlId from access_ctlauth where EmployeeId = '" + input.EmployeeId + "')");
                        var data = await _db.SqlQueryable<AccessCtlEntity>(dbSql.ToString()).ToListAsync();
                        foreach (var item in data)
                        {
                            var TaskCrInput = new AccessCtlauthTaskCrInput();
                            TaskCrInput.addorDel = 2;
                            TaskCrInput.ctlId = item.CtlId;
                            TaskCrInput.ctlSn = item.CtlSn;
                            TaskCrInput.ctlName = item.CtlName;
                            TaskCrInput.doorAreaId = item.DoorAreaId;
                            TaskCrInput.doorAreaName = item.DoorAreaName;
                            TaskCrInput.ctlposition = item.Ctlposition;
                            TaskCrInput.door1No = 1;
                            TaskCrInput.door2No = 1;
                            TaskCrInput.door3No = 1;
                            TaskCrInput.door4No = 1;
                            TaskCrInput.startTime = DateTime.Now;
                            TaskCrInput.endTime = DateTime.Now.AddDays(-1);
                            TaskCrInput.issues = 0;
                            TaskCrInput.employeeId = input.EmployeeId;
                            TaskCrInput.jobNo = EyeEntity.JobNum;
                            TaskCrInput.reallName = EyeEntity.RealName;
                            TaskCrInput.departId = EyeEntity.DepartId;
                            TaskCrInput.departName = EyeEntity.DepartName;
                            TaskCrInput.cardNo = EyeEntity.CardNo;
                            TaskCrInput.CompanyId = userInfo.companyId;
                            TaskCrInput.CompanyName = userInfo.companyName;
                            var Entity = TaskCrInput.Adapt<AccessCtlauthTaskEntity>();
                            Entity.Create();
                            Entity.IsDeleteTask = 1;
                            ctlauthTaskList.Add(Entity);
                        }
                        #endregion
                    }
                    if (ctlauthTaskList != null && ctlauthTaskList.Count > 0)
                    {
                        var isOk = await _db.Insertable(ctlauthTaskList).ExecuteCommandAsync();
                        if (!(isOk > 0)) throw PARKException.Oh(ErrorCode.COM1000);
                    }
                }
                catch (Exception ex)
                {
                    throw PARKException.Oh(ex.Message);
                }
            }
            else
                throw PARKException.Bah("您的权限无法操作!");
        }
        #endregion

        /// <summary>
        /// 删除权限管理
        /// </summary>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public async Task Delete(string id)
        {
            var userInfo = await _userManager.GetUserInfo();
            if (userInfo != null && userInfo.UserAdminFlag != 2 && !string.IsNullOrEmpty(userInfo.companyId))
            {
                var entity = await _db.Queryable<AccessCtlauthTaskEntity>().FirstAsync(p => p.TaskId == id);
                _ = entity ?? throw PARKException.Oh(ErrorCode.COM1005);
                entity.Delete();
                var isOk = await _db.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
                if (!(isOk > 0)) throw PARKException.Oh(ErrorCode.COM1002);
            }
            else
            {
                throw PARKException.Bah("您的权限无法操作!");
            }
        }
    }
}
